/**
 * Create an image element from a file
 * @param file Image file
 * @returns Promise with HTMLImageElement
 */
export async function createImageFromFile(file: File): Promise<HTMLImageElement> {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => resolve(img);
    img.onerror = () => reject(new Error('Failed to load image'));
    img.src = URL.createObjectURL(file);
  });
}

/**
 * Create a canvas from an image
 * @param img Image element
 * @returns Canvas element
 */
export function createCanvasFromImage(img: HTMLImageElement): HTMLCanvasElement {
  const canvas = document.createElement('canvas');
  canvas.width = img.width;
  canvas.height = img.height;
  const ctx = canvas.getContext('2d');
  if (ctx) {
    ctx.drawImage(img, 0, 0);
  }
  return canvas;
}

/**
 * Get image format from file
 * @param file Image file
 * @returns Image format (jpg, png, etc.)
 */
export function getImageFormat(file: File): string {
  const name = file.name.toLowerCase();
  if (name.endsWith('.jpg') || name.endsWith('.jpeg')) {
    return 'jpg';
  } else if (name.endsWith('.png')) {
    return 'png';
  } else if (name.endsWith('.webp')) {
    return 'webp';
  } else {
    return 'unknown';
  }
}

/**
 * Convert canvas to blob
 * @param canvas Canvas element
 * @param format Image format
 * @param quality Image quality (0-1)
 * @returns Promise with Blob
 */
export function canvasToBlob(canvas: HTMLCanvasElement, format: string, quality: number): Promise<Blob> {
  return new Promise((resolve, reject) => {
    let mimeType: string;
    switch (format.toLowerCase()) {
      case 'jpg':
      case 'jpeg':
        mimeType = 'image/jpeg';
        break;
      case 'png':
        mimeType = 'image/png';
        break;
      case 'webp':
        mimeType = 'image/webp';
        break;
      default:
        mimeType = 'image/jpeg';
    }

    canvas.toBlob(
      (blob) => {
        if (blob) {
          resolve(blob);
        } else {
          reject(new Error('Failed to convert canvas to blob'));
        }
      },
      mimeType,
      quality
    );
  });
}

/**
 * Calculate optimal grid dimensions for a given number of images
 * @param count Number of images
 * @returns [rows, columns]
 */
export function calculateGridDimensions(count: number): [number, number] {
  const sqrt = Math.sqrt(count);
  const cols = Math.ceil(sqrt);
  const rows = Math.ceil(count / cols);
  return [rows, cols];
}

import { createPerfectSquareLayout } from './perfectSquareLayout';

/**
 * 优化的网格布局算法，考虑图片方向，尽量生成接近正方形的输出
 * @param images 要排列的图片数组
 * @param spacing 图片之间的间距
 * @returns 优化后的图片位置数组和画布尺寸
 */
export function optimizeGridLayout(
  images: Array<{ id: string; name: string; width: number; height: number; format: string }>,
  spacing: number
): { positions: Array<{ id: string; name: string; x: number; y: number; width: number; height: number; format: string }>; width: number; height: number } {
  // 如果图片数量为0，返回空结果
  if (images.length === 0) {
    return { positions: [], width: 0, height: 0 };
  }

  // 复制图片数组，避免修改原数组
  const imagesCopy = [...images];

  // 将图片分为横向和纵向两组
  const landscapeImages = imagesCopy.filter(img => img.width > img.height);
  const portraitImages = imagesCopy.filter(img => img.width <= img.height);

  // 检查是否有横竖混合的图片
  const hasLandscape = landscapeImages.length > 0;
  const hasPortrait = portraitImages.length > 0;
  const isMixed = hasLandscape && hasPortrait;

  // 初始化结果
  const positions: Array<{ id: string; name: string; x: number; y: number; width: number; height: number; format: string }> = [];

  // 特殊情况：3张4000*6000 + 3张6000*4000的图片
  if (images.length === 6 && 
      landscapeImages.length === 3 && 
      portraitImages.length === 3 && 
      areSimilarSizes(landscapeImages) && 
      areSimilarSizes(portraitImages)) {
    
    // 检查是否符合特定尺寸比例
    const typicalLandscape = landscapeImages[0];
    const typicalPortrait = portraitImages[0];
    
    // 检查横向图片的宽是否约等于纵向图片的高，横向图片的高是否约等于纵向图片的宽
    const isSpecialCase = Math.abs(typicalLandscape.width - typicalPortrait.height) < 100 &&
                         Math.abs(typicalLandscape.height - typicalPortrait.width) < 100;
    
    if (isSpecialCase) {
      // 使用特殊的布局来创建12000*12000的正方形
      return createPerfectSquareLayout(landscapeImages, portraitImages, spacing);
    }
  }

  // 特殊情况处理：横竖图片数量相等且比例接近
  if (isMixed && landscapeImages.length === portraitImages.length) {
    // 检查是否所有横向图片尺寸相似，所有纵向图片尺寸相似
    const isLandscapeSimilar = areSimilarSizes(landscapeImages);
    const isPortraitSimilar = areSimilarSizes(portraitImages);

    if (isLandscapeSimilar && isPortraitSimilar) {
      // 使用特殊的矩形布局
      return optimizeRectangularLayout(landscapeImages, portraitImages, spacing);
    }
  }

  // 特殊情况：所有图片尺寸相似
  if (areSimilarSizes(images)) {
    // 尝试生成接近正方形的布局
    return createSquareLikeLayout(images, spacing);
  }

  // 一般情况：使用改进的网格布局
  let currentX = 0;
  let currentY = 0;
  let rowHeight = 0;
  let maxWidth = 0;
  let maxHeight = 0;

  // 按照面积从大到小排序图片，这样可以优先放置大图
  const sortedImages = [...imagesCopy].sort((a, b) => (b.width * b.height) - (a.width * a.height));

  // 计算基本的网格尺寸
  const totalCount = images.length;
  const [_, baseCols] = calculateGridDimensions(totalCount);

  // 如果是混合图片，尝试先放置所有横向图片，再放置纵向图片
  const allImages = isMixed
    ? [...landscapeImages.sort((a, b) => b.width - a.width), ...portraitImages.sort((a, b) => b.height - a.height)]
    : sortedImages;

  // 使用改进的网格布局算法
  for (let i = 0; i < allImages.length; i++) {
    const img = allImages[i];

    // 如果这是一个新行的开始
    if (currentX === 0) {
      rowHeight = 0;
    }

    // 检查当前行是否还能放下这张图片
    const maxRowWidth = isMixed ?
      Math.max(...allImages.map(img => img.width)) * baseCols :
      baseCols * (sortedImages[0].width + spacing);

    if (i > 0 && currentX + img.width + spacing > maxRowWidth) {
      // 移到下一行
      currentX = 0;
      currentY += rowHeight + spacing;
      rowHeight = 0;
    }

    // 放置图片
    positions.push({
      id: img.id,
      name: img.name,
      x: currentX,
      y: currentY,
      width: img.width,
      height: img.height,
      format: img.format
    });

    // 更新当前位置和行高
    currentX += img.width + spacing;
    rowHeight = Math.max(rowHeight, img.height);

    // 更新最大宽度和高度
    maxWidth = Math.max(maxWidth, currentX - spacing);
    maxHeight = Math.max(maxHeight, currentY + rowHeight);
  }

  return {
    positions,
    width: maxWidth,
    height: maxHeight
  };
}

/**
 * 检查一组图片的尺寸是否相似
 * @param images 图片数组
 * @returns 是否相似
 */
function areSimilarSizes(images: Array<{ width: number; height: number }>): boolean {
  if (images.length <= 1) return true;

  const firstWidth = images[0].width;
  const firstHeight = images[0].height;

  // 允许10%的误差
  const tolerance = 0.1;

  return images.every(img =>
    Math.abs(img.width - firstWidth) / firstWidth < tolerance &&
    Math.abs(img.height - firstHeight) / firstHeight < tolerance
  );
}

/**
 * 针对横竖图片数量相等的情况优化布局
 * @param landscapeImages 横向图片数组
 * @param portraitImages 纵向图片数组
 * @param spacing 图片间距
 * @returns 优化后的布局
 */
function optimizeRectangularLayout(
  landscapeImages: Array<{ id: string; name: string; width: number; height: number; format: string }>,
  portraitImages: Array<{ id: string; name: string; width: number; height: number; format: string }>,
  spacing: number
): { positions: Array<{ id: string; name: string; x: number; y: number; width: number; height: number; format: string }>; width: number; height: number } {
  const positions: Array<{ id: string; name: string; x: number; y: number; width: number; height: number; format: string }> = [];

  // 计算最佳的行列数
  const count = landscapeImages.length + portraitImages.length;
  const [baseRows, baseCols] = calculateGridDimensions(count);

  // 对于您提到的特殊情况：3张横向 + 3张纵向
  if (landscapeImages.length === 3 && portraitImages.length === 3) {
    // 假设所有横向图片尺寸相似，所有纵向图片尺寸相似
    const typicalLandscape = landscapeImages[0];
    const typicalPortrait = portraitImages[0];

    // 检查是否符合您描述的情况：4000*6000 和 6000*4000
    const isSpecialCase = Math.abs(typicalLandscape.width - typicalPortrait.height) < 100 &&
      Math.abs(typicalLandscape.height - typicalPortrait.width) < 100;

    if (isSpecialCase) {
      // 使用特殊的2x3布局
      // 第一行：2个横向图片
      // 第二行：1个横向图片 + 2个纵向图片
      // 第三行：1个纵向图片

      let currentX = 0;
      let currentY = 0;

      // 第一行：2个横向图片
      for (let i = 0; i < 2; i++) {
        positions.push({
          id: landscapeImages[i].id,
          name: landscapeImages[i].name,
          x: currentX,
          y: currentY,
          width: landscapeImages[i].width,
          height: landscapeImages[i].height,
          format: landscapeImages[i].format
        });
        currentX += landscapeImages[i].width + spacing;
      }

      // 移到第二行
      currentY += landscapeImages[0].height + spacing;
      currentX = 0;

      // 第二行：1个横向图片
      positions.push({
        id: landscapeImages[2].id,
        name: landscapeImages[2].name,
        x: currentX,
        y: currentY,
        width: landscapeImages[2].width,
        height: landscapeImages[2].height,
        format: landscapeImages[2].format
      });
      currentX += landscapeImages[2].width + spacing;

      // 第二行：2个纵向图片
      for (let i = 0; i < 2; i++) {
        positions.push({
          id: portraitImages[i].id,
          name: portraitImages[i].name,
          x: currentX,
          y: currentY,
          width: portraitImages[i].width,
          height: portraitImages[i].height,
          format: portraitImages[i].format
        });
        currentX += portraitImages[i].width + spacing;
      }

      // 移到第三行
      currentY += Math.max(landscapeImages[2].height, portraitImages[0].height) + spacing;
      currentX = 0;

      // 第三行：1个纵向图片
      positions.push({
        id: portraitImages[2].id,
        name: portraitImages[2].name,
        x: currentX,
        y: currentY,
        width: portraitImages[2].width,
        height: portraitImages[2].height,
        format: portraitImages[2].format
      });

      // 计算总宽度和高度
      const width = Math.max(
        landscapeImages[0].width + spacing + landscapeImages[1].width,
        landscapeImages[2].width + spacing + portraitImages[0].width + spacing + portraitImages[1].width,
        portraitImages[2].width
      );

      const height = landscapeImages[0].height + spacing +
        Math.max(landscapeImages[2].height, portraitImages[0].height) + spacing +
        portraitImages[2].height;

      return { positions, width, height };
    }
  }

  // 一般情况：尝试创建一个紧凑的布局
  let currentX = 0;
  let currentY = 0;
  let rowHeight = 0;
  let maxWidth = 0;

  // 先放置所有横向图片
  for (let i = 0; i < landscapeImages.length; i++) {
    const img = landscapeImages[i];

    // 检查当前行是否还能放下这张图片
    if (i > 0 && currentX + img.width > baseCols * img.width) {
      // 移到下一行
      currentX = 0;
      currentY += rowHeight + spacing;
      rowHeight = 0;
    }

    // 放置图片
    positions.push({
      id: img.id,
      name: img.name,
      x: currentX,
      y: currentY,
      width: img.width,
      height: img.height,
      format: img.format
    });

    // 更新当前位置和行高
    currentX += img.width + spacing;
    rowHeight = Math.max(rowHeight, img.height);
    maxWidth = Math.max(maxWidth, currentX - spacing);
  }

  // 移到下一行
  if (landscapeImages.length > 0) {
    currentX = 0;
    currentY += rowHeight + spacing;
    rowHeight = 0;
  }

  // 再放置所有纵向图片
  for (let i = 0; i < portraitImages.length; i++) {
    const img = portraitImages[i];

    // 检查当前行是否还能放下这张图片
    if (i > 0 && currentX + img.width > baseCols * img.width) {
      // 移到下一行
      currentX = 0;
      currentY += rowHeight + spacing;
      rowHeight = 0;
    }

    // 放置图片
    positions.push({
      id: img.id,
      name: img.name,
      x: currentX,
      y: currentY,
      width: img.width,
      height: img.height,
      format: img.format
    });

    // 更新当前位置和行高
    currentX += img.width + spacing;
    rowHeight = Math.max(rowHeight, img.height);
    maxWidth = Math.max(maxWidth, currentX - spacing);
  }

  // 计算总高度
  const height = currentY + rowHeight;

  return { positions, width: maxWidth, height };
}

/**
 * 创建接近正方形的布局，适用于所有图片尺寸相似的情况
 * @param images 图片数组
 * @param spacing 图片间距
 * @returns 优化后的布局
 */
function createSquareLikeLayout(
  images: Array<{ id: string; name: string; width: number; height: number; format: string }>,
  spacing: number
): { positions: Array<{ id: string; name: string; x: number; y: number; width: number; height: number; format: string }>; width: number; height: number } {
  const positions: Array<{ id: string; name: string; x: number; y: number; width: number; height: number; format: string }> = [];

  if (images.length === 0) {
    return { positions, width: 0, height: 0 };
  }

  // 计算所有图片的平均宽度和高度
  const avgWidth = images.reduce((sum, img) => sum + img.width, 0) / images.length;
  const avgHeight = images.reduce((sum, img) => sum + img.height, 0) / images.length;

  // 计算总面积（包括间距）
  const totalArea = images.reduce((sum, img) => sum + img.width * img.height, 0);

  // 计算理想的正方形边长
  const idealSideLength = Math.sqrt(totalArea);

  // 计算理想的行数和列数
  // 我们希望行数和列数尽可能接近，以创建接近正方形的布局
  let rows = Math.round(Math.sqrt(images.length));
  let cols = Math.ceil(images.length / rows);

  // 调整行数和列数，使布局更接近正方形
  // 考虑图片的平均宽高比
  const aspectRatio = avgWidth / avgHeight;
  if (aspectRatio > 1) {
    // 横向图片，增加列数
    cols = Math.ceil(cols * Math.sqrt(aspectRatio));
    rows = Math.ceil(images.length / cols);
  } else if (aspectRatio < 1) {
    // 纵向图片，增加行数
    rows = Math.ceil(rows * Math.sqrt(1 / aspectRatio));
    cols = Math.ceil(images.length / rows);
  }

  // 特殊情况：6张相同尺寸的图片（如6张4000*6000的图片）
  if (images.length === 6 && areSimilarSizes(images)) {
    const firstImg = images[0];
    const isPortrait = firstImg.height > firstImg.width;

    if (isPortrait) {
      // 对于纵向图片（如4000*6000），使用3x2的网格布局
      rows = 2;
      cols = 3;
    } else {
      // 对于横向图片（如6000*4000），使用2x3的网格布局
      rows = 3;
      cols = 2;
    }
  }

  let currentX = 0;
  let currentY = 0;
  let rowHeight = 0;

  // 按照计算出的行列数排列图片
  for (let i = 0; i < images.length; i++) {
    const img = images[i];

    // 如果这是一个新行的开始
    if (i % cols === 0) {
      currentX = 0;
      if (i > 0) {
        currentY += rowHeight + spacing;
      }
      rowHeight = 0;
    }

    // 放置图片
    positions.push({
      id: img.id,
      name: img.name,
      x: currentX,
      y: currentY,
      width: img.width,
      height: img.height,
      format: img.format
    });

    // 更新当前位置和行高
    currentX += img.width + spacing;
    rowHeight = Math.max(rowHeight, img.height);
  }

  // 计算总宽度和高度
  const width = Math.min(
    cols * (avgWidth + spacing) - spacing,
    positions.reduce((max, pos) => Math.max(max, pos.x + pos.width), 0)
  );

  const height = currentY + rowHeight;

  return { positions, width, height };
}